import { getUploadSignature, saveFileMetadata } from '@/api/file'
import { useUploadStore, UploadStatus } from '@/stores/upload'

// 上传签名响应接口
interface UploadSignatureResponse {
  accessid: string
  policy: string
  signature: string
  dir: string
  host: string
  key: string
  expire: number
}

// 文件上传工具类
export class FileUploader {
  private uploadStore = useUploadStore()

  /**
   * 上传单个文件
   */
  async uploadFile(taskId: string): Promise<void> {
    const task = this.uploadStore.tasks.find(t => t.id === taskId)
    if (!task) {
      throw new Error('上传任务不存在')
    }

    try {
      // 1. 获取上传签名
      const signatureData = await getUploadSignature({
        fileName: task.file.name,
        fileSize: task.file.size,
        contentType: task.file.type || 'application/octet-stream',
        parentId: task.parentId
      })

      // 2. 上传到OSS
      await this.uploadToOSS(taskId, signatureData)

      // 3. 保存文件元数据
      await this.saveFileMetadata(taskId, signatureData.key)

      // 4. 标记为成功
      this.uploadStore.updateTask(taskId, {
        status: UploadStatus.SUCCESS,
        progress: 100
      })

    } catch (error: any) {
      // 处理错误
      this.uploadStore.updateTask(taskId, {
        status: UploadStatus.ERROR,
        errorMessage: error.message || '上传失败'
      })
      throw error
    } finally {
      // 启动下一个上传任务
      this.uploadStore.startNextUpload()
    }
  }

  /**
   * 上传文件到OSS
   */
  private async uploadToOSS(taskId: string, signatureData: UploadSignatureResponse): Promise<void> {
    const task = this.uploadStore.tasks.find(t => t.id === taskId)
    if (!task) {
      throw new Error('上传任务不存在')
    }

    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()

      // 保存XHR实例以便取消
      this.uploadStore.updateTask(taskId, { xhr })

      // 监听上传进度
      xhr.upload.addEventListener('progress', (event) => {
        if (event.lengthComputable) {
          this.uploadStore.updateProgress(taskId, event.loaded, event.total)
        }
      })

      // 监听状态变化
      xhr.addEventListener('readystatechange', () => {
        if (xhr.readyState === XMLHttpRequest.DONE) {
          if (xhr.status >= 200 && xhr.status < 300) {
            resolve()
          } else {
            reject(new Error(`OSS上传失败: HTTP ${xhr.status}`))
          }
        }
      })

      // 监听错误
      xhr.addEventListener('error', () => {
        reject(new Error('网络错误'))
      })

      // 监听取消
      xhr.addEventListener('abort', () => {
        reject(new Error('上传已取消'))
      })

      // 构造表单数据
      const formData = new FormData()
      formData.append('key', signatureData.key)
      formData.append('policy', signatureData.policy)
      formData.append('OSSAccessKeyId', signatureData.accessid)
      formData.append('signature', signatureData.signature)
      formData.append('file', task.file)

      // 发送请求
      xhr.open('POST', signatureData.host)
      xhr.send(formData)
    })
  }

  /**
   * 保存文件元数据到数据库
   */
  private async saveFileMetadata(taskId: string, ossKey: string): Promise<void> {
    const task = this.uploadStore.tasks.find(t => t.id === taskId)
    if (!task) {
      throw new Error('上传任务不存在')
    }

    await saveFileMetadata({
      fileName: task.file.name,
      fileSize: task.file.size,
      fileType: task.file.type || 'application/octet-stream',
      parentId: task.parentId,
      ossKey: ossKey
    })
  }

  /**
   * 批量上传文件
   */
  async uploadFiles(files: FileList | File[], parentId: number): Promise<string[]> {
    const taskIds: string[] = []

    // 添加所有文件到上传队列
    Array.from(files).forEach(file => {
      // 验证文件大小（10GB限制）
      if (file.size > 10 * 1024 * 1024 * 1024) {
        console.warn(`文件 ${file.name} 超过10GB限制，已跳过`)
        return
      }

      const taskId = this.uploadStore.addTask(file, parentId)
      taskIds.push(taskId)
    })

    // 显示上传对话框
    if (taskIds.length > 0) {
      this.uploadStore.showDialog()
    }

    // 开始处理上传队列
    this.processUploadQueue()

    return taskIds
  }

  /**
   * 处理上传队列
   */
  private async processUploadQueue(): Promise<void> {
    const checkAndStartUploads = () => {
      const uploadingTasks = this.uploadStore.uploadingTasks

      // 为每个正在上传的任务启动上传
      for (const task of uploadingTasks) {
        if (!task.xhr) { // 避免重复启动
          this.uploadFile(task.id).catch(error => {
            console.error(`文件 ${task.fileName} 上传失败:`, error)
          })
        }
      }

      // 如果还有待上传的任务，延迟检查
      if (this.uploadStore.tasks.some(t => t.status === 'waiting')) {
        setTimeout(checkAndStartUploads, 100)
      }
    }

    checkAndStartUploads()
  }

  /**
   * 取消所有上传
   */
  cancelAllUploads(): void {
    this.uploadStore.clearAllTasks()
  }

  /**
   * 验证文件类型和大小
   */
  validateFile(file: File): { valid: boolean; message?: string } {
    // 检查文件大小
    if (file.size > 10 * 1024 * 1024 * 1024) {
      return {
        valid: false,
        message: '文件大小不能超过10GB'
      }
    }

    // 检查文件名
    if (!file.name || file.name.trim() === '') {
      return {
        valid: false,
        message: '文件名不能为空'
      }
    }

    // 检查文件名长度
    if (file.name.length > 255) {
      return {
        valid: false,
        message: '文件名长度不能超过255个字符'
      }
    }

    // 检查危险文件类型（可根据需要扩展）
    const dangerousExtensions = ['.exe', '.bat', '.cmd', '.scr', '.pif', '.com']
    const fileExtension = file.name.toLowerCase().substring(file.name.lastIndexOf('.'))
    if (dangerousExtensions.includes(fileExtension)) {
      return {
        valid: false,
        message: '不支持该文件类型'
      }
    }

    return { valid: true }
  }
}

// 创建全局实例
export const fileUploader = new FileUploader()